<?php
/**
 * 用 curl 进行抓取
 */

class Spider_Grabber_Curl extends Spider_Grabber_Abstract {

    /**
     * 创建实例
     * @return type
     * @throws Spider_Grabber_Exception
     */
    private function _create() {

        if(!function_exists('curl_init')) {
            throw new Spider_Grabber_Exception('curl not found', Spider_Grabber_Exception::E_SPIDER_GRABBER_INIT_ERROR);
        }
        $ch = curl_init();
        if(false === $ch || !is_resource($ch)) {
            throw new Spider_Grabber_Exception('curl create failed', Spider_Grabber_Exception::E_SPIDER_GRABBER_INIT_ERROR);
        }
        return $ch;
    }

    /**
     * 抓取指定链接内容
     * @param <type> $url
     * @param <type> $cookie
     * @param <type> $httpHeader
     * @param <type> $ignoreCache
     * @return <type>
     */
    public function fetchSource($url, $cookie = null, $httpHeader = null, $ignoreCache = false) {

        if (!$ignoreCache && false !== ($content = $this->_fetchCache($url))) {
            return $content;
        }

        $ret = $this->_execute('GET', $url, '', $this->_userAgent, $httpHeader, $cookie, $this->_username, $this->_password);
        if(false === $ret || is_array($ret)) {
            return null;
        }

        $this->_saveCache($url, $ret);
        return $ret;
    }

    /**
     * 发送请求获取返回内容
     * @param type $method
     * @param type $url
     * @param type $fields
     * @param type $userAgent
     * @param type $httpHeaders
     * @param type $username
     * @param type $password
     * @return boolean
     */
    private function _execute($method, $url, $fields = '', $userAgent = '', $httpHeaders = '', $cookie = '', $username = '', $password = '') {

        $ch = $this->_create();
        if (is_string($url) && strlen($url)) {
            curl_setopt($ch, CURLOPT_URL, $url);
        } else {
            return false;
        }

        //是否显示头部信息
        curl_setopt($ch, CURLOPT_HEADER, false);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($username != '') {
            curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
        }
        $method = strtolower($method);
        if ('post' == $method) {
            curl_setopt($ch, CURLOPT_POST, true);
            if (is_array($fields)) {
                $sets = array();
                foreach ($fields AS $key => $val) {
                    $sets[] = $key . '=' . urlencode($val);
                }
                $fields = implode('&', $sets);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
        } else if ('put' == $method) {
            curl_setopt($ch, CURLOPT_PUT, true);
        }
//         curl_setopt($ch, CURLOPT_PROGRESS, true);
//         curl_setopt($ch, CURLOPT_VERBOSE, true);
//         curl_setopt($ch, CURLOPT_MUTE, false);

        //设置curl超时秒数
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);

        // user agent
        if (is_array($userAgent)) {
            $idx = array_rand($userAgent);
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent[$idx]);
        } elseif (strlen($userAgent) > 0) {
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
        }

        // http 头
        if(is_array($httpHeaders)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
        }

        // cookie
        if ($cookie) {
            if (is_array($cookie)) {
                $cookieArray = array();
                foreach ($cookie as $k => $v) {
                    $cookieArray[] = $k.'='.  urlencode($v);
                }
                $cookie = implode('; ', $cookieArray);
            }
            curl_setopt($ch, CURLOPT_COOKIE, $cookie);
        }

        // execute & return
        $ret = curl_exec($ch);
        if(curl_errno($ch) || !is_string($ret) || !strlen($ret)) {
            curl_close($ch);
            return false;
        }
        curl_close($ch);
        return $ret;
    }
}
